package twoD.IsoPfem.EmbeddedCrackModel;

import inf.jlinalg.IMatrix;

import java.util.ArrayList;

import twoD.IsoPfem.Mesh;
import twoD.IsoPfem.RealTable;
import twoD.IsoPfem.Structure;

public class CrackStructure extends Structure {

	protected ArrayList<IEmbeddedCrackElement> elements_;

	private ICrackInitiationCondition cIC_;
	private LoadingFunction lF_;
	private RealTable realTable_;

	public CrackStructure(Mesh M) {
		super(M);
		elements_ = new ArrayList<IEmbeddedCrackElement>();
	}

	public void setCrackInitiationCondition(ICrackInitiationCondition cic) {
		cIC_ = cic;
	}

	public void setLoadingFunction(LoadingFunction lf) {
		lF_ = lf;
	}

	public LoadingFunction getLoadingFunction() {
		return lF_;
	}

	public IEmbeddedCrackElement addElement(IEmbeddedCrackElement e) {
		elements_.add(e);
		return e;
	}

	@Override
	public IEmbeddedCrackElement getElements(int i) {
		return elements_.get(i);
	}

	@Override
	public int getNumberOfElements() {
		return elements_.size();
	}

	public void setRealTable(RealTable rt) {
		realTable_ = rt;
	}

	@Override
	public void assembleTangentStiffnessMatrix(IMatrix kGlobal, boolean full) {
		for (int i = 0; i < getNumberOfElements(); i++) {
			IMatrix ke;
			if (getElements(i).isCrack()) {
				ke = getElements(i).computeTangentStiffnessMatrix(lF_,
						realTable_.getDhat2D());
				// System.out.println("ke" + i + "=" + MatrixFormat.format(ke));
			} else {
				ke = getElements(i).computeTangentStiffnessMatrix();
			}
			ArrayList<Integer> dofNumbers = elements_.get(i).getDOFNumbers();
			int l = dofNumbers.size();
			for (int p = 0; p < l; p++)
				for (int q = full ? 0 : p; q < l; q++)
					if (dofNumbers.get(p) != -1 && dofNumbers.get(q) != -1)
						kGlobal.add(dofNumbers.get(p), dofNumbers.get(q),
								ke.get(p, q));
		}
	}

	private ArrayList<Integer> crackElementList = new ArrayList<Integer>();

	/**
	 * 
	 * @return the maximum max-principal stress in the structure
	 */
	public double checkCrackInitiationCondition() {
		double sigmamax = 0.0;
		for (int i = 0; i < getNumberOfElements(); i++) {
			double[] sigma1 = elements_.get(i).computeSigma1();

			if (cIC_.check(sigma1[0]))
				if (!getElements(i).isCrack()) {
					getElements(i).setCrack(true);
					crackElementList.add(i);
					getElements(i).setCrackSlope(
							Math.atan2(sigma1[2], sigma1[1]));
					// getElements(i).setFirstTimeCrack(true);
					// System.out.println("crack element " + i + ":");
					getElements(i).fixCrack();
					// fix the crack (i.e fix the matrix A and H for the
					// element)
				}
			if (sigma1[0] > sigmamax)
				sigmamax = sigma1[0];
		}
		System.out
				.println("Checking crack initiation complete, crack element = "
						+ crackElementList.toString());
		return sigmamax;
	}

	public void updateCrackingState() {
		IMatrix Dhat = realTable_.getDhat2D();
		for (int i = 0; i < getNumberOfElements(); i++) {
			if (getElements(i).isCrack()) {
				System.out.println("-->Internal equilibrium for crack element "
						+ i + ":");
				getElements(i).checkFirstTimeCrack(lF_, realTable_.getDhat2D());
				getElements(i).updateCrackingState(lF_, Dhat);
				System.out.println("-->End of loop for crack element " + i);
			}
		}
	}

	@Override
	public void updateGlobalState() {
		// checking crack initiation condition
		double sigmamax = checkCrackInitiationCondition();
		System.out.println("Maximum stress in the system = " + sigmamax
				+ ", tensile strength = "
				+ lF_.getTractionSeparationLaw().getTensileStrength());
		// update crack compliance parameters and crack opening parameters of
		// the element
		updateCrackingState();
	}

	@Override
	public void updateInternalState() {
		// update crack compliance parameters and crack opening parameters of
		// the element
		updateCrackingState();
	}

	@Override
	public void solveStaticEquilibrium() {
		Iterate();
	}

	@Override
	public void solveStaticEquilibrium(double lambda) {
		Iterate(lambda);
	}
}
